// 获取画布比例9：16
// 先创建素材
const bgImage = new Image();bgImage.src = "./bg.png";
const userplane = new Image();userplane.src = "./1.png";
const enemyplane = new Image();enemyplane.src = "./2.png";
const bullet1 = new Image();bullet1.src = "./bullet2.png";
const bullet2 = new Image();bullet2.src = "./bullet1.png";
const enemydown1 = new Image();enemydown1.src = "./2down1.png";
const enemydown2 = new Image();enemydown2.src = "./2down2.png";
const enemydown3 = new Image();enemydown3.src = "./2down3.png";
const enemydown4 = new Image();enemydown4.src = "./2down4.png";
const zd = new Image();zd.src = "./zd.png";
const zdnum = new Image();zdnum.src = "./zdnum.png";
/**
 * 判断是否碰撞
 * 因为只记录的飞机的x,y坐标所有要加上size,才是飞机的面积
 */

class Game {
  constructor() {
    this.Images = {
      0:enemyplane,
      1:enemydown1,
      2:enemydown2,
      3:enemydown3,
      4:enemydown4,
      zd:zd,
      zdnum:zdnum
    }
    this.size = 50; // 格子大小
    this.bulletSize = 10; // 子弹大小
    this.requestAFId = null;
    this.isGameOver = false; // 是否开始游戏
    this.isGameOver = false;
    this.cvs = document.getElementById("canvas"),
    this.ctx = document.getElementById("canvas").getContext("2d"),
    this.config = {
      width: this.size * 9,
      height: this.size * 16,
      offsetLeft:this.cvs.offsetLeft,
      offsetTop:this.cvs.offsetTop,
    };

    this.planeSpeed = 2;  // 飞机移动速度
    this.userBulletSpeed = 10; // 玩家子弹移动速度
    this.enemyBulletSpeed = 3; // 敌人子弹移动速度
    this.userBulletStep = 200; // 玩家子弹间隔时间
    this.enemyBulletStep = 1500; // 敌人子弹间隔时间
    this.bullets = {user:[],enemy:[]}; // 子弹数组 enemy弃用
    this.lifeNum = 3;
    this.life = this.lifeNum;
    this.userPointer = {x: this.size *4,y: this.size * 15,width:this.size,height:this.size}; // 玩家飞机坐标
    this.enemyPointer = [{
      x: this.size * 4,
      y: 0,is:false,
      width:this.size,
      height:this.size,
      destroyStep:0,
      image:this.Images[0],
      bullet:[]}
    ]  // 敌人飞机坐标
    this.enemyPlaneNum = 50;     // 场上敌人飞机数量
    this.enemyPlaneStep = 500;   // 生成敌人飞机间隔
    this.touchEnter = false;     // 是否点击到玩家飞机
    this.collision = false;      // 是否碰撞
    this.score = 0;              // 分数
    this.enemyDestroyTime = 200; // 敌人飞机销毁时间

    this.enemyBulletSetI = null; // 敌人子弹定时器
    this.userBulletSetI = null;  // 玩家子弹定时器
    this.enemyCreateSetI = null; // 生成敌机定时器

    // 炸弹
    this.zdSpeed = 5;
    this.zdStep = 1;
    this.zdnum = 0;
    this.zd = [];

    this.startBg();
    this.addEvent();
  }
  gameStart(){
    if(!this.isActive){
      this.isActive = true;
      this.init();
    }
  }
  startBg(){
    const cvs = this.cvs;
    const ctx = this.ctx;
    this.BG(cvs,ctx)
    ctx.font = '50px 宋体';
    ctx.fillText("点击开始",cvs.width / 2 - 100 , cvs.height / 2);
  }
  //重新开始
  restart(){
    this.clearEnemyCreateSetI();
    this.isActive = false;
    this.isGameOver = false;
    this.life = this.lifeNum;
    this.zdStep = 1;
    this.zdnum = 0;
    this.zd = [];
    clearInterval(this.enemyBulletSetI);
    clearInterval(this.userBulletSetI);
    clearInterval(this.enemyCreateSetI);
    this.score = 0;
    this.enemyPointer = [];
    this.userPointer = {x: this.size *4,y: this.size * 15,width:this.size,height:this.size};
  }
  restartBg(){
    this.restart();
    const cvs = this.cvs;
    const ctx = this.ctx;
    cvs.removeEventListener("mousedown", this.mousedownFn);
    this.mouseupFn();
    ctx.clearRect(0, 0, cvs.width, cvs.height);
    this.BG(cvs,ctx);
    ctx.font = '50px 宋体';
    console.log(this.userPointer)
    ctx.fillText("点击重新开始",cvs.width / 2 - 100 - 50 , cvs.height / 2);
    this.addEvent();
  }

  // 清除敌人飞机定时器
  clearEnemyCreateSetI(){
    for(let i = 0; i < this.enemyPointer.length; i++){
      const item = this.enemyPointer[i];
      clearInterval(item.setInterval);
    }
  }
  init() {
    const { width, height } = this.config;
    const cvs = this.cvs;
    cvs.width = width;
    cvs.height = height;
    
    this.render();
    this.enemyCreate();
    this.enemyBullet();
    this.userBullet();
    this.enemyBulletSetI = setInterval(() => {
      this.enemyBullet();
    }, this.enemyBulletStep);
    this.userBulletSetI = setInterval(() => {
      this.userBullet();
    }, this.userBulletStep);
  }
  // 生成炸弹道具
  zdCreate() {
    const step = this.score / this.zdStep;
    if(step == 100){
      ++this.zdStep;
      const obj = {
        x:this.getRandom(0,8) * this.size,
        y:0,
        width:this.size,
        height:this.size
      }
      this.zd.push(obj);
    }
  }
  // 判断是否触碰到炸弹道具
  touchzd(){
    this.zdMove();
    for(let i = 0; i < this.zd.length; i++){
      const item = this.zd[i];
      if(this.isCollisionFn(item,this.userPointer)){
        this.zd.splice(i,1);
        this.zdnum++;
      }
    }
  }
  zdMove(){
    for(let i = 0; i < this.zd.length; i++){
      const item = this.zd[i];
      if(item.y < this.cvs.height){
        item.y += this.zdSpeed;
      }else{
        this.zd.splice(i,1);
      }
    }
  }
  // 绘制炸弹
  drawzd() {
    this.touchzd();
    for(let i = 0; i < this.zd.length; i++){
      const item = this.zd[i];
      this.ctx.drawImage(this.Images.zd, item.x, item.y, this.size, this.size);
    }
  }
  // 绘制炸弹数量
  drawzdnum() {
    this.ctx.drawImage(this.Images.zdnum, this.cvs.width -this.size*2, 20, this.size, this.size);
    this.ctx.font = "30px 宋体";
    this.ctx.fillStyle = "yellow";
    this.ctx.fillText(this.zdnum, this.cvs.width -this.size + 10, this.size);
  }
  // 使用炸弹
  usezd() {
    if(this.zdnum <= 0) return;
    this.zdnum--;
    this.usezdAll()
  }
  // 使用炸弹请出屏幕所有敌人
  usezdAll() {
    this.isBulletCollision(true);
  }
  // 获取随机数
  getRandom(min, max) {
    return Math.random() * (max - min + 1) + min;
  }
  drawScore(){
    this.ctx.font = "20px 宋体";
    this.ctx.fillStyle = "yellow";
    this.ctx.fillText(this.score + '分', 10, 20);
  }
  // 背景
  BG(cvs,ctx) {
    const { width, height } = this.config;
    ctx.clearRect(0, 0, width, height);
    cvs.width = width;
    cvs.height = height;
    ctx.drawImage(bgImage, 0, 0, width, height);
  }
  // 生成玩家发射子弹
  userBullet() {
    const { x, y } = this.userPointer;
    this.bullets.user.push({ x:x + this.size / 2 - 3.5, y:y - 25,width:this.bulletSize,height:this.bulletSize*2});
  }
  // 生成敌人子弹
  enemyBullet() {
    if(this.enemyPointer.length <= 0) return;
    for(let i = 0; i < this.enemyPointer.length; i++){
      if(this.enemyPointer[i].is) continue;
      const { x, y } = this.enemyPointer[i];
      const item = this.enemyPointer[i];
      item.bullet.push({bulletX:x + this.size / 2 - 3.5,bulletY:y + 25,bulletWidth:this.bulletSize,bulletHeight:this.bulletSize*2})
    }
  }
  // 绘制所有子弹
  bulletDraw(ctx) {
    for (let i = 0; i < this.bullets.user.length; i++) {
      const { x, y,width,height } = this.bullets.user[i];
      ctx.drawImage(bullet1, x, y, width, height);
    }
    for (let i = 0; i < this.enemyPointer.length; i++) {
      const item = this.enemyPointer[i];
      for(let j = 0; j < item.bullet.length; j++){
        const { bulletX:x,bulletY:y,bulletWidth:width,bulletHeight:height } = item.bullet[j];
        ctx.drawImage(bullet2, x, y, width, height);
      }
    }
  }
  // 子弹移动
  bulletMove() {
    for (let i = 0; i < this.bullets.user.length; i++) {
      const { y } = this.bullets.user[i];
      this.bullets.user[i].y -= this.userBulletSpeed;
      if (y <= 0) {
        this.bullets.user.splice(i, 1);
        i--;
      }
    }
    for (let i = 0; i < this.enemyPointer.length; i++) {
      const item = this.enemyPointer[i];
      if(item.is == true && item.bullet.length == 0 && !item.setInterval){
        this.enemyPointer.splice(i, 1);
        continue;
      }
      for(let j = 0; j < item.bullet.length; j++){
        const itemJ = item.bullet[j];
        itemJ.bulletY += this.enemyBulletSpeed;
        if (itemJ.bulletY >= this.config.height) {
          item.bullet.splice(i, 1);
        }
      }
    }
    this.bulletHit();
  }
  // 子弹抵消
  bulletHit() {
    this.enemyPointer.map(itemp => {
      itemp.bullet.map((itemb,indexb) => {
        this.bullets.user.map((itemu,indexu) => {
          if(this.isCollisionFn(itemu,{x:itemb.bulletX,y:itemb.bulletY,width:itemb.bulletWidth,height:itemb.bulletHeight})){
            itemp.bullet.splice(indexb, 1);
            this.bullets.user.splice(indexu, 1);
          }
        })
      })
    })
  }
  // 生成敌人飞机
  enemyCreate(){
    this.enemyCreateSetI = setInterval(() => {
      this.enemyCreateFn();
    }, this.enemyPlaneStep);
  }
  enemyCreateFn(){
    if(this.enemyPointer.length >= this.enemyPlaneNum) return;
    const x = this.getRandom(0,8);
    this.enemyPointer.push({x:x * this.size,y:0,is:false,width:this.size,height:this.size,destroyStep:0,image:this.Images[0],bullet:[]});
  }
  // 绘制敌对飞机
  enemy(ctx) {
    for(let i = 0; i < this.enemyPointer.length; i++){
      const item = this.enemyPointer[i];
      if(item.is && item.destroyStep >= 4) {
        continue;
      };
      const { x, y,image } = this.enemyPointer[i];
      ctx.drawImage(image, x, y, this.size, this.size);
    }
  }
  // 绘制被击毁的动画
  enemyDestroy(item) {
      if(item.destroyStep >= 4){
        clearInterval(item.setInterval);
        item.setInterval = null;
      };
      item.destroyStep++;
      item.image = this.Images[item.destroyStep];
  }

  // 判断是否碰撞
  isCollision(){
    for(let i = 0; i < this.enemyPointer.length; i++){
      const item = this.enemyPointer[i];
      if(item.is) continue;
      if(this.isCollisionFn(this.userPointer,item)){
        --this.life;
        this.enemyPointer.splice(i, 1);
        if(this.life == 0){
          this.isGameOver = true;
        }
      }
    }
  }
  // 判断矩形是否相交
  isCollisionFn(rectangle1, rectangle2) {
    const x1 = rectangle1.x;
    const y1 = rectangle1.y;
    const width1 = rectangle1.width;
    const height1 = rectangle1.height;

    const x2 = rectangle2.x;
    const y2 = rectangle2.y;
    const width2 = rectangle2.width;
    const height2 = rectangle2.height;

    const left1 = x1;
    const right1 = x1 + width1;
    const top1 = y1;
    const bottom1 = y1 + height1;

    const left2 = x2;
    const right2 = x2 + width2;
    const top2 = y2;
    const bottom2 = y2 + height2;

    return !(right1 < left2 || left1 > right2 || bottom1 < top2 || top1 > bottom2);
  }
  // 判断子弹是否击中敌人或被击中
  // is:清空敌人
  isBulletCollision(is = false){
    for(let i = 0; i < this.enemyPointer.length; i++){
      const item = this.enemyPointer[i];
      if(is){
        this.score += 10;
        item.is = true;
        item.destroyStep = 1;
        item.image = this.Images[item.destroyStep];
        item.bullet = [];
        if(item.setInterval)return;
        item.setInterval = setInterval(() => {
          this.enemyDestroy(item);
        }, this.enemyDestroyTime);
        continue;
      }
      if(item.is) continue;
      if(this.isBulletCollisionFn(item)){
        this.score += 10;
        item.is = true;
        item.destroyStep = 1;
        item.image = this.Images[item.destroyStep];
        
        if(item.setInterval)return;
        item.setInterval = setInterval(() => {
          this.enemyDestroy(item);
        }, this.enemyDestroyTime);
      }
    }
    for(let i = 0; i < this.enemyPointer.length; i++){
      const item = this.enemyPointer[i];
      for(let j = 0; j < item.bullet.length; j++){
        const itemJ = item.bullet[j];
        const obj = {
          x:itemJ.bulletX,
          y:itemJ.bulletY,
          width:itemJ.bulletWidth,
          height:itemJ.bulletHeight
        }
        if(this.isCollisionFn(this.userPointer,obj)){
          --this.life;
          item.bullet.splice(j,1)
          if(this.life == 0){
            this.isGameOver = true;
          }
        }
      }
    }
  }
  // 是否击中敌人
  isBulletCollisionFn(plane) {
    for (let i = 0; i < this.bullets.user.length; i++) {
      if(this.isCollisionFn(this.bullets.user[i],{x:plane.x,y:plane.y,width:plane.width,height:plane.height})){
        return true;
      }
    }
  }
  // 生成玩家
  player(ctx) {
    const { x, y } = this.userPointer;
    ctx.beginPath();
    ctx.drawImage(userplane, x, y, this.size, this.size);
    ctx.rect(x,y,this.size, this.size);
    ctx.stroke()
    ctx.closePath();
    this.drawLife();
  }
  // 绘制生命条
  drawLife() {
    const { x, y } = this.userPointer;
    const ctx = this.ctx;
    const step = this.lifeNum / this.life;
    ctx.beginPath();
    ctx.rect(x,y - 10,this.size,10);
    ctx.stroke();
    ctx.closePath();
    ctx.beginPath();
    ctx.rect(x + 1,y - 9,this.size / step,8)
    ctx.fillStyle = "red";
    ctx.fill();
    ctx.closePath();
  }
  // 敌对飞机移动
  enemyMove() {
    for (let i = 0; i < this.enemyPointer.length; i++) {
      const item = this.enemyPointer[i];
      if(item.is)continue;

      item.y += this.planeSpeed;
      if(item.y >= this.size * 16){

        this.enemyPointer.splice(i,1);
      }
    }
    this.isBulletCollision();
    this.isCollision();
  }
  // 渲染
  render() {
    const cvs = this.cvs;
    const ctx = this.ctx;
    this.BG(cvs,ctx);
    this.player(ctx);
    this.enemy(ctx);
    this.bulletMove();
    this.bulletDraw(ctx);
    this.enemyMove();
    this.zdCreate();
    this.drawzd();
    this.drawScore();
    this.drawzdnum();
    if(this.isGameOver){
      cancelAnimationFrame(this.requestAFId);
      alert("游戏结束");
      this.restartBg();
    }else{
      this.requestAFId = requestAnimationFrame(() => {
        this.render();
      })
    }
  }
  // 判断是否点击到飞机
  isTouchPlane = (init) => {
    const { x: ux, y: uy } = this.userPointer;
    const { x, y } = init;
    if (x >= ux && x <= ux + this.size && y >= uy && y <= uy + this.size) {
      this.touchEnter = true;
    } else {
      this.touchEnter = false;
    }
  };
  // 添加事件
  mousedownFn = ({ clientX: x, clientY: y }) => {
    if(!this.isActive){
      this.gameStart();
      return;
    }
    const {offsetLeft:left,offsetTop:top} = this.cvs;
    const e = { x: x - left, y: y - top };
    this.isTouchPlane(e);
    if (this.touchEnter) {
      document.addEventListener("mousemove", this.mousemoveFn,false);
      document.addEventListener("mouseup", this.mouseupFn);
    }
  };
  mousemoveFn = ({offsetX,offsetY}) => {
    if (!this.touchEnter) return;
    const { offsetLeft: left, offsetTop: top } = this.cvs;
    const x = offsetX - left - this.size / 2;
    const y = offsetY - top - this.size / 2;
    this.userPointer.x = x;
    this.userPointer.y = y
  };
  mouseupFn = () => {
    document.removeEventListener("mousemove", this.mousemoveFn);
    document.removeEventListener("mouseup", this.mouseupFn);
  };
  // 空格按键
  keydownFn = (e) => {
    if (e.keyCode == 32) {
      this.usezd();
    }
  };
  addEvent = () => {
    const canvas = this.cvs;
    document.addEventListener('keydown',this.keydownFn)
    canvas.addEventListener("mousedown", this.mousedownFn);
  };
}
let game;
function start() {
  if (game) {
    game.re();
  }
  game = new Game();
}
window.onload = () => {
  game = new Game();
};
